/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ec.socialfun.servicios;

import com.ec.socialfun.entidades.Evento;
import com.ec.socialfun.entidades.EventoUsuario;
import com.ec.socialfun.entidades.Usuario;
import com.ec.socialfun.enumeradores.EstadoEnum;
import com.ec.socialfun.excepciones.RecuperaEventoUsuarioException;
import com.ec.socialfun.excepciones.RegistrarReservaException;
import com.ec.socialfun.util.Consulta;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Stateless;
import javax.ejb.TransactionAttribute;
import javax.ejb.TransactionAttributeType;
import javax.persistence.EntityManager;
import javax.persistence.NoResultException;
import javax.persistence.NonUniqueResultException;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import org.jboss.logging.Logger;

/**
 *
 * @author hp
 */
@Stateless
public class EventoUsuarioFacade extends AbstractFacade<EventoUsuario> {

    private static final Logger LOG = Logger.getLogger(EventoUsuarioFacade.class.getName());
    @PersistenceContext(unitName = "SocialFunPU")
    private EntityManager em;
    @EJB
    private UsuarioFacade usuarioFacade;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public EventoUsuarioFacade() {
        super(EventoUsuario.class);
    }

    public Consulta recuperarEventosUsuario(Consulta consulta) {

        // consulta para conteo total de datos
        StringBuilder sbContador = new StringBuilder();
        sbContador.append("SELECT COUNT(e) FROM EventoUsuario e WHERE e.usCodigo.usCorreo = :usCorreo");


        // consulta obtencio de datos
        StringBuilder sbConsulta = new StringBuilder();
        sbConsulta.append("SELECT e FROM EventoUsuario e WHERE e.usCodigo.usCorreo = :usCorreo");

        if (consulta.getColumnaOrdenar() != null && consulta.getTipoDeOrdenamiento() != null) {
            sbConsulta.append(" ORDER BY ").append(consulta.getColumnaOrdenar()).append(" ").append(consulta.getTipoDeOrdenamiento().getCodigo());
        }
        LOG.info("sbContador = " + sbContador.toString());
        LOG.info("sbConsulta = " + sbConsulta.toString());

        Query q = em.createQuery(sbContador.toString());
        q.setParameter("usCorreo", consulta.getUsuarioLogeado());
        consulta.setContador((Long) q.getSingleResult());

        q = em.createQuery(sbConsulta.toString());
        q.setParameter("usCorreo", consulta.getUsuarioLogeado());
        q.setFirstResult(consulta.getPrimerRegistro());
        q.setMaxResults(consulta.getTamanoPagina());
        consulta.setLista(q.getResultList());

        return consulta;
    }

    /**
     * busca reserva por evento y usuario en estado RESERVADO
     *
     * @param evento
     * @param usuario
     * @return
     */
    public EventoUsuario recuperarEventoUsuarioReservado(Evento evento, Usuario usuario) {
        try {
            LOG.info("Consulta EVENTO USUARIO");
            Query q = em.createNamedQuery("EventoUsuario.recuperarEventoUsuarioReservado");
            q.setParameter("evento", evento.getEvCodigo());
            q.setParameter("usuario", usuario.getUsCodigo());
            q.setParameter("estado", EstadoEnum.RESERVADO.getCodigo());
            return (EventoUsuario) q.getSingleResult();
        } catch (NoResultException e) {
            LOG.info("CATCH ");
            return null;
        }

    }
    
     public List<EventoUsuario> recuperarListaEventoUsuarioReservado(Integer evCodigo) {
        try {
            LOG.info("Consulta EVENTO USUARIO");
            Query q = em.createNamedQuery("EventoUsuario.recuperarUsuariosConReserva");
            q.setParameter("evCodigo", evCodigo);
            q.setParameter("estado", EstadoEnum.RESERVADO.getCodigo());
            LOG.info("LISTA "+q.getResultList()); 
            return q.getResultList();
        } catch (NoResultException e) {
            LOG.info("CATCH ");
            return null;
        }

    }

    /**
     * realiza la reserva de un evento para el usuario
     *
     * @param eventoUsuario
     * @param mail
     * @param evento
     * @throws RegistrarReservaException
     */
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void registrarReserva(EventoUsuario eventoUsuario, String mail, Evento evento) throws RegistrarReservaException {
        try {

            eventoUsuario.setEvCodigo(evento);
            eventoUsuario.setUsCodigo(usuarioFacade.recuperaUsuarioPorMail(mail));
            eventoUsuario.setEvUsEstado(EstadoEnum.RESERVADO.getCodigo());
            if (eventoUsuario.getEvUsCodigo() == null) {
                this.create(eventoUsuario);
            } else {
                this.edit(eventoUsuario);
            }

        } catch (Exception e) {
            LOG.error("Error al registrar reserva " + e);
            throw new RegistrarReservaException("Error al registrar la reserva");
        }
    }

    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void cancelarReserva(EventoUsuario eventoUsuario, String mail, Evento evento) throws RegistrarReservaException {
        try {

            eventoUsuario.setEvCodigo(evento);
            eventoUsuario.setUsCodigo(usuarioFacade.recuperaUsuarioPorMail(mail));
            eventoUsuario.setEvUsEstado(EstadoEnum.CANCELADO.getCodigo());
            this.edit(eventoUsuario);
        } catch (Exception e) {
            LOG.error("Error al cancelar reserva " + e);
            throw new RegistrarReservaException("Error al cancelar la reserva");
        }
    }

    /**
     * Recupera la reserva por evento y usuario independiente del estado
     *
     * @param evento
     * @param mailUsuario
     * @return
     * @throws RecuperaEventoUsuarioException
     */
    public EventoUsuario recuperarEventoUsuario(Evento evento, String mailUsuario) throws RecuperaEventoUsuarioException {
        try {

            Usuario usuario = usuarioFacade.recuperaUsuarioPorMail(mailUsuario);
            Query q = em.createNamedQuery("EventoUsuario.recuperarEventoUsuarioPorUsuarioYEvento");
            q.setParameter("evento", evento.getEvCodigo());
            q.setParameter("usuario", usuario.getUsCodigo());
            return (EventoUsuario) q.getSingleResult();
        } catch (NoResultException e) {
            throw new RecuperaEventoUsuarioException("No existe reserva para el usuario " + mailUsuario + " y el evento: " + evento.getEvCodigo());
        }catch(NonUniqueResultException e){
            throw new RecuperaEventoUsuarioException("No existe reserva para el usuario " + mailUsuario + " y el evento: " + evento.getEvCodigo());
        }

    }
}
